package com.weixin.project.Service;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.weixin.project.Common.Exception.FileNotValidException;
import com.weixin.project.Config.Config;
import com.weixin.project.Util.ResponseUtil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import org.springframework.core.io.Resource;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.UUID;

@Service
public class OSSService {
    @Value("${spring.aliyun.oss.bucket-name}")
    private String bucketName;
    @Value("${document.imagePath}")
    String uploadPath;
    @Autowired
    private OSS ossClient;

    /**
     * 上传图片
     * @param file 图片文件
     * @return
     * @throws IOException
     */
    public String uploadImage(MultipartFile file) throws IOException {
        String oldName = file.getOriginalFilename();
        //获取后缀
        int dotIndex = oldName.lastIndexOf(".");
        if (dotIndex == -1) throw new FileNotValidException("jpg,png");
        String extension = oldName.substring(dotIndex + 1);
        if (!extension.equals("jpg")&&!extension.equals("png")) throw new FileNotFoundException("json");
        System.out.println(extension);
        String fileName = UUID.randomUUID().toString() + "." + extension;
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, file.getInputStream());
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType("image/" + extension); //设置文件格式
        metadata.setContentDisposition("inline");
        putObjectRequest.setMetadata(metadata);
        PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
        String url = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/images/")
                .path(fileName)
                .toUriString();
        return url;
    }

    public String uploadJSON(MultipartFile file) throws IOException{
        String oldName = file.getOriginalFilename();
        //获取后缀
        int dotIndex = oldName.lastIndexOf(".");
        if (dotIndex == -1) throw new FileNotValidException("json");
        String extension = oldName.substring(dotIndex + 1);
        System.out.println("extension:" + extension);
        if (!extension.equals("json")) throw new FileNotValidException("json");
        String fileName = UUID.randomUUID().toString() + "." + extension;
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, file.getInputStream());
        PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
        String url = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/json/")
                .path(fileName)
                .toUriString();
        return url;
    }

    public String readJsonFileFromOSS(String url) {
        String[] split = url.split("/");
        String key = split[split.length - 1];
        OSSObject ossObject = ossClient.getObject(bucketName, key);
        BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent(), StandardCharsets.UTF_8));
        StringBuilder stringBuilder = new StringBuilder();
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return stringBuilder.toString();
    }

    public Resource downloadImage(String fileName){
        return new InputStreamResource(ossClient.getObject(bucketName, fileName).getObjectContent());
    }

    public Resource downloadJSON(String fileName){
        return new InputStreamResource(ossClient.getObject(bucketName, fileName).getObjectContent());
    }

    public String temporaryURL(String fileName){
        return ossClient.generatePresignedUrl(
                bucketName, fileName, new Date(System.currentTimeMillis() + 3600 * 1000)).toString();
    }

    /**
     * 上传视频
     * @param file MultipartFile mp4文件
     * @return JSONObject {
     *     "url": 视频路径，
     *     “cover_path": 封面路径
     * }
     * @throws IOException
     */
    public JSONObject uploadVideo(MultipartFile file) throws IOException {
        String fileName = UUID.randomUUID().toString() + ".mp4";
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, file.getInputStream());
        PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
        String url = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/download-video/")
                .path(fileName)
                .toUriString();
        String temporaryURL = ossClient.generatePresignedUrl(
                bucketName, fileName, new Date(System.currentTimeMillis() + 3600 * 1000)).toString();
        System.out.println("temporartURL:" +  temporaryURL);
        JSONObject ret = new JSONObject();
        ret.put("url", url);
        ret.put("cover_path", extractVideoCover(temporaryURL));
        return ret;
    }

    public Resource downloadVideo(String fileName){
        System.out.println("下载视频");
        return new InputStreamResource(ossClient.getObject(bucketName, fileName).getObjectContent());
    }

    private String extractVideoCover(String videoUrl) throws IOException {
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(videoUrl);
//        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(file);
        grabber.start();
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage image = converter.getBufferedImage(grabber.grabImage());
        grabber.stop();
        if (image == null) {
            throw new RuntimeException("Failed to extract frame from video.");
        }
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", outputStream);
        String newName = UUID.randomUUID().toString() + ".jpg";
        // 上传到 OSS
        InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, newName, inputStream);
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType("image/jpeg"); // 设置文件格式
        metadata.setContentDisposition("inline");
        putObjectRequest.setMetadata(metadata);
        ossClient.putObject(putObjectRequest);
        String url = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/images/")
                .path(newName)
                .toUriString();
        return url;

//        File folder = new File(uploadPath);
//        if (!folder.isDirectory()) {
//            folder.mkdirs();
//        }
//        String newName = UUID.randomUUID().toString() + ".jpg";
//        StringBuilder sb = new StringBuilder();
//        sb.append(Config.EXPOSE_IMAGE_BASE);
//        sb.append(newName);
//        File coverFile = new File(folder, newName);
//        ImageIO.write(image, "jpg", outputStream);
//        FileOutputStream fileOutputStream = new FileOutputStream(coverFile);
//        fileOutputStream.write(outputStream.toByteArray());
//        fileOutputStream.close();
//        return sb.toString();
    }

    public void deleteFile(String url){
        String[] split = url.split("/");
        String objectName = split[split.length - 1];
        try {
            // 删除文件。
            ossClient.deleteObject(bucketName, objectName);
        } catch (Exception e) {
            System.out.println("ERROR: failed to delete mp4 file on OSS");
            System.out.println(e.toString());
        }
    }
}
